#ifndef CORTEX_M3_H_
#define CORTEX_M3_H_

#include <stdint.h>

/*
 * ==========================================================================
 * ---------- Interrupt Number Definition -----------------------------------
 * ==========================================================================
 */

typedef enum IRQn
{
/******  Cortex-M3 Processor Exceptions Numbers ***************************************************/
  NonMaskableInt_IRQn           = -14,    /*!<  2 Cortex-M3 Non Maskable Interrupt                        */
  HardFault_IRQn                = -13,    /*!<  3 Cortex-M3 Hard Fault Interrupt                          */
  MemoryManagement_IRQn         = -12,    /*!<  4 Cortex-M3 Memory Management Interrupt            */
  BusFault_IRQn                 = -11,    /*!<  5 Cortex-M3 Bus Fault Interrupt                    */
  UsageFault_IRQn               = -10,    /*!<  6 Cortex-M3 Usage Fault Interrupt                  */
  SVCall_IRQn                   = -5,     /*!< 11 Cortex-M3 SV Call Interrupt                      */
  DebugMonitor_IRQn             = -4,     /*!< 12 Cortex-M3 Debug Monitor Interrupt                */
  PendSV_IRQn                   = -2,     /*!< 14 Cortex-M3 Pend SV Interrupt                      */
  SysTick_IRQn                  = -1,     /*!< 15 Cortex-M3 System Tick Interrupt                  */

/******  CM3DS_MPS2 Specific Interrupt Numbers *******************************************************/
  UARTRX_IRQn                   = 0,       /* UART 0 RX Interrupt                   */
  UARTTX_IRQn                   = 1,       /* UART 0 TX Interrupt                   */
  UARTOVR_IRQn                  = 2,       /* UART 0 overrun Interrupt              */
  TIMER_IRQn                    = 3        /* TIMER count Interrupt                 */
} IRQn_Type;


/*
 * ==========================================================================
 * ----------- Processor and Core Peripheral Section ------------------------
 * ==========================================================================
 */

/* Configuration of the Cortex-M3 Processor and Core Peripherals */
#define __CM3_REV                 0x0201    /*!< Core Revision r2p1                             */
#define __NVIC_PRIO_BITS          3         /*!< Number of Bits used for Priority Levels        */
#define __Vendor_SysTickConfig    0         /*!< Set to 1 if different SysTick Config is used   */
#define __MPU_PRESENT             1         /*!< MPU present or not                             */

#include "core_cm3.h"


/*
 * ==========================================================================
 * ----------- Device Specific Peripheral registers structures --------------
 * ==========================================================================
 */

/*----------- Universal Asynchronous Receiver Transmitter (UART) -----------*/
typedef struct
{
  __IO   uint32_t  DATA;          /*!< Offset: 0x000 Data Register    (R/W) */
  __IO   uint32_t  STATE;         /*!< Offset: 0x004 Status Register  (R/W) */
  __IO   uint32_t  CTRL;          /*!< Offset: 0x008 Control Register (R/W) */
  union {
    __I    uint32_t  INTSTATUS;   /*!< Offset: 0x00C Interrupt Status Register (R/ ) */
    __O    uint32_t  INTCLEAR;    /*!< Offset: 0x00C Interrupt Clear Register ( /W) */
    };
  __IO   uint32_t  BAUDDIV;       /*!< Offset: 0x010 Baudrate Divider Register (R/W) */

} UART_TypeDef;

/* _UART DATA Register Definitions */

#define UART_DATA_Pos               0                                            /*!< UART_DATA_Pos: DATA Position */
#define UART_DATA_Msk              (0xFFul << UART_DATA_Pos)               /*!< UART DATA: DATA Mask */

#define UART_STATE_RXOR_Pos         3                                            /*!< UART STATE: RXOR Position */
#define UART_STATE_RXOR_Msk         (0x1ul << UART_STATE_RXOR_Pos)         /*!< UART STATE: RXOR Mask */

#define UART_STATE_TXOR_Pos         2                                            /*!< UART STATE: TXOR Position */
#define UART_STATE_TXOR_Msk         (0x1ul << UART_STATE_TXOR_Pos)         /*!< UART STATE: TXOR Mask */

#define UART_STATE_RXBF_Pos         1                                            /*!< UART STATE: RXBF Position */
#define UART_STATE_RXBF_Msk         (0x1ul << UART_STATE_RXBF_Pos)         /*!< UART STATE: RXBF Mask */

#define UART_STATE_TXBF_Pos         0                                            /*!< UART STATE: TXBF Position */
#define UART_STATE_TXBF_Msk         (0x1ul << UART_STATE_TXBF_Pos )        /*!< UART STATE: TXBF Mask */

#define UART_CTRL_HSTM_Pos          6                                            /*!< UART CTRL: HSTM Position */
#define UART_CTRL_HSTM_Msk          (0x01ul << UART_CTRL_HSTM_Pos)         /*!< UART CTRL: HSTM Mask */

#define UART_CTRL_RXORIRQEN_Pos     5                                            /*!< UART CTRL: RXORIRQEN Position */
#define UART_CTRL_RXORIRQEN_Msk     (0x01ul << UART_CTRL_RXORIRQEN_Pos)    /*!< UART CTRL: RXORIRQEN Mask */

#define UART_CTRL_TXORIRQEN_Pos     4                                            /*!< UART CTRL: TXORIRQEN Position */
#define UART_CTRL_TXORIRQEN_Msk     (0x01ul << UART_CTRL_TXORIRQEN_Pos)    /*!< UART CTRL: TXORIRQEN Mask */

#define UART_CTRL_RXIRQEN_Pos       3                                            /*!< UART CTRL: RXIRQEN Position */
#define UART_CTRL_RXIRQEN_Msk       (0x01ul << UART_CTRL_RXIRQEN_Pos)      /*!< UART CTRL: RXIRQEN Mask */

#define UART_CTRL_TXIRQEN_Pos       2                                            /*!< UART CTRL: TXIRQEN Position */
#define UART_CTRL_TXIRQEN_Msk       (0x01ul << UART_CTRL_TXIRQEN_Pos)      /*!< UART CTRL: TXIRQEN Mask */

#define UART_CTRL_RXEN_Pos          1                                            /*!< UART CTRL: RXEN Position */
#define UART_CTRL_RXEN_Msk          (0x01ul << UART_CTRL_RXEN_Pos)         /*!< UART CTRL: RXEN Mask */

#define UART_CTRL_TXEN_Pos          0                                            /*!< UART CTRL: TXEN Position */
#define UART_CTRL_TXEN_Msk          (0x01ul << UART_CTRL_TXEN_Pos)         /*!< UART CTRL: TXEN Mask */

#define UART_INTSTATUS_RXORIRQ_Pos  3                                            /*!< UART CTRL: RXORIRQ Position */
#define UART_CTRL_RXORIRQ_Msk       (0x01ul << UART_INTSTATUS_RXORIRQ_Pos) /*!< UART CTRL: RXORIRQ Mask */

#define UART_CTRL_TXORIRQ_Pos       2                                            /*!< UART CTRL: TXORIRQ Position */
#define UART_CTRL_TXORIRQ_Msk       (0x01ul << UART_CTRL_TXORIRQ_Pos)      /*!< UART CTRL: TXORIRQ Mask */

#define UART_CTRL_RXIRQ_Pos         1                                            /*!< UART CTRL: RXIRQ Position */
#define UART_CTRL_RXIRQ_Msk         (0x01ul << UART_CTRL_RXIRQ_Pos)        /*!< UART CTRL: RXIRQ Mask */

#define UART_CTRL_TXIRQ_Pos         0                                            /*!< UART CTRL: TXIRQ Position */
#define UART_CTRL_TXIRQ_Msk         (0x01ul << UART_CTRL_TXIRQ_Pos)        /*!< UART CTRL: TXIRQ Mask */

#define UART_BAUDDIV_Pos            0                                            /*!< UART BAUDDIV: BAUDDIV Position */
#define UART_BAUDDIV_Msk            (0xFFFFFul << UART_BAUDDIV_Pos)        /*!< UART BAUDDIV: BAUDDIV Mask */

/*------------------ General Purpose Input Output (GPIO) -------------------*/
typedef struct
{
  __IO   uint32_t  DATA;                     /* Offset: 0x000 (R/W) DATA Register */
  __IO   uint32_t  DATAOUT;                  /* Offset: 0x004 (R/W) Data Output Latch Register */
         uint32_t  RESERVED0[2];
  __IO   uint32_t  OUTENABLESET;             /* Offset: 0x010 (R/W) Output Enable Set Register */
  __IO   uint32_t  OUTENABLECLR;             /* Offset: 0x014 (R/W) Output Enable Clear Register */
  __IO   uint32_t  ALTFUNCSET;               /* Offset: 0x018 (R/W) Alternate Function Set Register */
  __IO   uint32_t  ALTFUNCCLR;               /* Offset: 0x01C (R/W) Alternate Function Clear Register */
  __IO   uint32_t  INTENSET;                 /* Offset: 0x020 (R/W) Interrupt Enable Set Register */
  __IO   uint32_t  INTENCLR;                 /* Offset: 0x024 (R/W) Interrupt Enable Clear Register */
  __IO   uint32_t  INTTYPESET;               /* Offset: 0x028 (R/W) Interrupt Type Set Register */
  __IO   uint32_t  INTTYPECLR;               /* Offset: 0x02C (R/W) Interrupt Type Clear Register */
  __IO   uint32_t  INTPOLSET;                /* Offset: 0x030 (R/W) Interrupt Polarity Set Register */
  __IO   uint32_t  INTPOLCLR;                /* Offset: 0x034 (R/W) Interrupt Polarity Clear Register */
  union {
    __I    uint32_t  INTSTATUS;              /* Offset: 0x038 (R/ ) Interrupt Status Register */
    __O    uint32_t  INTCLEAR;               /* Offset: 0x038 ( /W) Interrupt Clear Register */
    };
         uint32_t RESERVED1[241];
  __IO   uint32_t LB_MASKED[256];            /* Offset: 0x400 - 0x7FC Lower byte Masked Access Register (R/W) */
  __IO   uint32_t UB_MASKED[256];            /* Offset: 0x800 - 0xBFC Upper byte Masked Access Register (R/W) */
} GPIO_TypeDef;

/* _GPIO DATA Register Definitions */

#define GPIO_DATA_Pos            0                                          /* GPIO DATA: DATA Position */
#define GPIO_DATA_Msk            (0xFFFFul << GPIO_DATA_Pos)          /* GPIO DATA: DATA Mask */

#define GPIO_DATAOUT_Pos         0                                          /* GPIO DATAOUT: DATAOUT Position */
#define GPIO_DATAOUT_Msk         (0xFFFFul << GPIO_DATAOUT_Pos)       /* GPIO DATAOUT: DATAOUT Mask */

#define GPIO_OUTENSET_Pos        0                                          /* GPIO OUTEN: OUTEN Position */
#define GPIO_OUTENSET_Msk        (0xFFFFul << GPIO_OUTEN_Pos)         /* GPIO OUTEN: OUTEN Mask */

#define GPIO_OUTENCLR_Pos        0                                          /* GPIO OUTEN: OUTEN Position */
#define GPIO_OUTENCLR_Msk        (0xFFFFul << GPIO_OUTEN_Pos)         /* GPIO OUTEN: OUTEN Mask */

#define GPIO_ALTFUNCSET_Pos      0                                          /* GPIO ALTFUNC: ALTFUNC Position */
#define GPIO_ALTFUNCSET_Msk      (0xFFFFul << GPIO_ALTFUNC_Pos)       /* GPIO ALTFUNC: ALTFUNC Mask */

#define GPIO_ALTFUNCCLR_Pos      0                                          /* GPIO ALTFUNC: ALTFUNC Position */
#define GPIO_ALTFUNCCLR_Msk      (0xFFFFul << GPIO_ALTFUNC_Pos)       /* GPIO ALTFUNC: ALTFUNC Mask */

#define GPIO_INTENSET_Pos        0                                          /* GPIO INTEN: INTEN Position */
#define GPIO_INTENSET_Msk        (0xFFFFul << GPIO_INTEN_Pos)         /* GPIO INTEN: INTEN Mask */

#define GPIO_INTENCLR_Pos        0                                          /* GPIO INTEN: INTEN Position */
#define GPIO_INTENCLR_Msk        (0xFFFFul << GPIO_INTEN_Pos)         /* GPIO INTEN: INTEN Mask */

#define GPIO_INTTYPESET_Pos      0                                          /* GPIO INTTYPE: INTTYPE Position */
#define GPIO_INTTYPESET_Msk      (0xFFFFul << GPIO_INTTYPE_Pos)       /* GPIO INTTYPE: INTTYPE Mask */

#define GPIO_INTTYPECLR_Pos      0                                          /* GPIO INTTYPE: INTTYPE Position */
#define GPIO_INTTYPECLR_Msk      (0xFFFFul << GPIO_INTTYPE_Pos)       /* GPIO INTTYPE: INTTYPE Mask */

#define GPIO_INTPOLSET_Pos       0                                          /* GPIO INTPOL: INTPOL Position */
#define GPIO_INTPOLSET_Msk       (0xFFFFul << GPIO_INTPOL_Pos)        /* GPIO INTPOL: INTPOL Mask */

#define GPIO_INTPOLCLR_Pos       0                                          /* GPIO INTPOL: INTPOL Position */
#define GPIO_INTPOLCLR_Msk       (0xFFFFul << GPIO_INTPOL_Pos)        /* GPIO INTPOL: INTPOL Mask */

#define GPIO_INTSTATUS_Pos       0                                          /* GPIO INTSTATUS: INTSTATUS Position */
#define GPIO_INTSTATUS_Msk       (0xFFul << GPIO_INTSTATUS_Pos)       /* GPIO INTSTATUS: INTSTATUS Mask */

#define GPIO_INTCLEAR_Pos        0                                          /* GPIO INTCLEAR: INTCLEAR Position */
#define GPIO_INTCLEAR_Msk        (0xFFul << GPIO_INTCLEAR_Pos)        /* GPIO INTCLEAR: INTCLEAR Mask */

#define GPIO_MASKLOWBYTE_Pos     0                                          /* GPIO MASKLOWBYTE: MASKLOWBYTE Position */
#define GPIO_MASKLOWBYTE_Msk     (0x00FFul << GPIO_MASKLOWBYTE_Pos)   /* GPIO MASKLOWBYTE: MASKLOWBYTE Mask */

#define GPIO_MASKHIGHBYTE_Pos    0                                          /* GPIO MASKHIGHBYTE: MASKHIGHBYTE Position */
#define GPIO_MASKHIGHBYTE_Msk    (0xFF00ul << GPIO_MASKHIGHBYTE_Pos)  /* GPIO MASKHIGHBYTE: MASKHIGHBYTE Mask */

/*--------------------------------  I2C  -----------------------------------*/
typedef struct
{
  __IO    uint32_t  CONTROL;
  __IO    uint32_t  CONTROLC;
}I2C_TypeDef;

#define I2C_SCL_Pos  0
#define I2C_SCL_Msk  (1UL<<I2C_SCL_Pos)

#define I2C_SDA_Pos  1
#define I2C_SDA_Msk  (1UL<<I2C_SDA_Pos)

/*---------------------------- Timer (TIMER) -------------------------------*/
typedef struct
{
  __IO   uint32_t  CTRL;          /*!< Offset: 0x000 Control Register (R/W) */
  __IO   uint32_t  VALUE;         /*!< Offset: 0x004 Current Value Register (R/W) */
  __IO   uint32_t  RELOAD;        /*!< Offset: 0x008 Reload Value Register  (R/W) */
  union {
    __I    uint32_t  INTSTATUS;   /*!< Offset: 0x00C Interrupt Status Register (R/ ) */
    __O    uint32_t  INTCLEAR;    /*!< Offset: 0x00C Interrupt Clear Register ( /W) */
    };

} Timer_TypeDef;

/* TIMER CTRL Register Definitions */

#define TIMER_CTRL_IRQEN_Pos          3                                              /*!< TIMER CTRL: IRQEN Position */
#define TIMER_CTRL_IRQEN_Msk          (0x01ul << TIMER_CTRL_IRQEN_Pos)         /*!< TIMER CTRL: IRQEN Mask */

#define TIMER_CTRL_SELEXTCLK_Pos      2                                              /*!< TIMER CTRL: SELEXTCLK Position */
#define TIMER_CTRL_SELEXTCLK_Msk      (0x01ul << TIMER_CTRL_SELEXTCLK_Pos)     /*!< TIMER CTRL: SELEXTCLK Mask */

#define TIMER_CTRL_SELEXTEN_Pos       1                                              /*!< TIMER CTRL: SELEXTEN Position */
#define TIMER_CTRL_SELEXTEN_Msk       (0x01ul << TIMER_CTRL_SELEXTEN_Pos)      /*!< TIMER CTRL: SELEXTEN Mask */

#define TIMER_CTRL_EN_Pos             0                                              /*!< TIMER CTRL: EN Position */
#define TIMER_CTRL_EN_Msk             (0x01ul << TIMER_CTRL_EN_Pos)            /*!< TIMER CTRL: EN Mask */

#define TIMER_VAL_CURRENT_Pos         0                                              /*!< TIMER VALUE: CURRENT Position */
#define TIMER_VAL_CURRENT_Msk         (0xFFFFFFFFul << TIMER_VAL_CURRENT_Pos)  /*!< TIMER VALUE: CURRENT Mask */

#define TIMER_RELOAD_VAL_Pos          0                                              /*!< TIMER RELOAD: RELOAD Position */
#define TIMER_RELOAD_VAL_Msk          (0xFFFFFFFFul << TIMER_RELOAD_VAL_Pos)   /*!< TIMER RELOAD: RELOAD Mask */

#define TIMER_INTSTATUS_Pos           0                                              /*!< TIMER INTSTATUS: INTSTATUSPosition */
#define TIMER_INTSTATUS_Msk           (0x01ul << TIMER_INTSTATUS_Pos)          /*!< TIMER INTSTATUS: INTSTATUSMask */

#define TIMER_INTCLEAR_Pos            0                                              /*!< TIMER INTCLEAR: INTCLEAR Position */
#define TIMER_INTCLEAR_Msk            (0x01ul << TIMER_INTCLEAR_Pos)           /*!< TIMER INTCLEAR: INTCLEAR Mask */


/******************************************************************************/
/*                         Peripheral memory map                              */
/******************************************************************************/
/* Peripheral and SRAM base address */
#define ROM_BASE         (0x00000000UL)
#define SRAM_BASE        (0x20000000UL)

#define APB_BASE         (0x40000000UL)
#define UART_BASE        (APB_BASE + 0x0000UL)
#define I2C_BASE         (APB_BASE + 0x1000UL)
#define Timer_BASE       (APB_BASE + 0x2000UL)
#define GPIO0_BASE       (0x40010000UL)


/******************************************************************************/
/*                         Peripheral declaration                             */
/******************************************************************************/
#define UART             ((UART_TypeDef   *) UART_BASE   )
#define GPIO0            ((GPIO_TypeDef   *) GPIO0_BASE  )
#define I2C              ((I2C_TypeDef    *) I2C_BASE    )
#define Timer            ((Timer_TypeDef  *) Timer_BASE  )

#endif
